package com.csii.activiti.server.core.listener;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.csii.activiti.server.abstraction.constant.MessageType;
import com.csii.activiti.server.abstraction.entity.ActFlowRemoteCallback;
import com.csii.activiti.server.abstraction.entity.ActReceivedBy;
import com.csii.activiti.server.abstraction.entity.ActSendMessage;
import com.csii.activiti.server.abstraction.service.ActMessageService;
import com.csii.activiti.server.core.constant.CommonConstant;
import com.csii.activiti.server.core.entity.ActFlowNode;
import com.csii.activiti.server.core.entity.db.ActFlowPeopleWhoCopiedEntity;
import com.csii.activiti.server.core.entity.db.ActFlowPublishConfigEntity;
import com.csii.activiti.server.core.mapper.ActFlowNodeMapper;
import com.csii.activiti.server.core.mapper.ActFlowPublishConfigurationMapper;
import com.csii.activiti.server.core.service.FlowCallbackManagementService;
import com.csii.activiti.server.core.service.FlowPeopleWhoCopiedService;
import com.csii.activiti.server.core.utils.ELUtils;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.JavaDelegate;
import org.activiti.engine.impl.persistence.entity.ExecutionEntityImpl;
import org.activiti.engine.impl.persistence.entity.VariableInstance;
import org.activiti.engine.repository.ProcessDefinition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

@Component
@Slf4j
public class PeopleWhoCopiedDelegate implements JavaDelegate, Serializable {

    private static final long serialVersionUID = 1L;

    @Autowired
    private AuditorGlobalListener auditorGlobalListener;

    @Autowired
    private ActFlowNodeMapper actFlowNodeMapper;

    @Autowired
    private FlowPeopleWhoCopiedService flowPeopleWhoCopiedService;

    @Autowired
    private ActFlowPublishConfigurationMapper actFlowPublishConfigurationMapper;

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private ActMessageService actMessageService;

    @Autowired
    private FlowCallbackManagementService flowCallbackManagementService;

    @Override
    public void execute(DelegateExecution execution) {
        if (execution instanceof ExecutionEntityImpl){
            ExecutionEntityImpl executionEntity = (ExecutionEntityImpl) execution;
            String activityId = executionEntity.getActivityId();

            String processInstanceId = executionEntity.getProcessInstanceId();
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(executionEntity.getProcessDefinitionId()).singleResult();
            ActFlowPublishConfigEntity actFlowPublishConfigEntity = actFlowPublishConfigurationMapper.selectOne(new LambdaQueryWrapper<ActFlowPublishConfigEntity>().select(ActFlowPublishConfigEntity::getIconType,ActFlowPublishConfigEntity::getFlowName,ActFlowPublishConfigEntity::getSummary,ActFlowPublishConfigEntity::getManyConditionJson).eq(ActFlowPublishConfigEntity::getId, processDefinition.getDeploymentId()));
            String iconType = actFlowPublishConfigEntity.getIconType();
            ExecutionEntityImpl parentExecutionEntity = executionEntity.getParent();
            String processName = actFlowPublishConfigEntity.getFlowName();
            ActFlowNode actFlowNode = actFlowNodeMapper.selectById(activityId).transitionActFlowNode();
            Set<String> usernames = auditorGlobalListener.getApproveUsernames(actFlowNode, processInstanceId, processInstanceId,null);
            String taskId = executionEntity.getId();
            String initiator = parentExecutionEntity.getStartUserId();

            List<ActFlowPeopleWhoCopiedEntity> dataList = new ArrayList<>();
            for (String username : usernames) {
                ActFlowPeopleWhoCopiedEntity pwcEntity = new ActFlowPeopleWhoCopiedEntity();
                pwcEntity.setCreateTime(new Date());
                pwcEntity.setProcessName(processName);
                pwcEntity.setPwcUserName(username);
                pwcEntity.setNodeId(activityId);
                pwcEntity.setNodeName(actFlowNode.getNodeName());
                pwcEntity.setTaskId(taskId);
                pwcEntity.setInitiator(initiator);
                pwcEntity.setProcessInstanceId(processInstanceId);
                pwcEntity.setIconType(iconType);
                pwcEntity.setDeploymentId(processDefinition.getDeploymentId());
                pwcEntity.setActTenantId(processDefinition.getTenantId());
                dataList.add(pwcEntity);
            }
            flowPeopleWhoCopiedService.saveBatch(dataList);

            //发送消息
            ActSendMessage sendMessage = new ActSendMessage();
            sendMessage.setTenantId(parentExecutionEntity.getTenantId());
            sendMessage.setProcessName(processName);
            sendMessage.setProcessDefinitionId(parentExecutionEntity.getProcessDefinitionId());
            sendMessage.setProcessKey(parentExecutionEntity.getProcessDefinitionKey());
            sendMessage.setProcessInstanceId(parentExecutionEntity.getProcessInstanceId());
            sendMessage.setInitiator(parentExecutionEntity.getStartUserId());
            Map<String, Object> formData = (Map<String, Object>) parentExecutionEntity.getVariableInstance(CommonConstant.FORM_DATA).getValue();
            sendMessage.setFormData(formData);
            List<ActReceivedBy> receivedByList = dataList.stream().map(item-> new ActReceivedBy(item.getId(), item.getPwcUserName())).collect(Collectors.toList());
            sendMessage.setReceivedByList(receivedByList);
            sendMessage.setCurrentNodeId(activityId);
            sendMessage.setCurrentNodeName(actFlowNode.getNodeName());
            VariableInstance callbackVariableInstance = parentExecutionEntity.getVariableInstance(CommonConstant.REMOTE_URL);
            if (callbackVariableInstance != null){
                sendMessage.setCallbackList((List<ActFlowRemoteCallback>) callbackVariableInstance.getValue());
            }
            sendMessage.setCurrentDate(new Date());
            if(actFlowPublishConfigEntity != null){
                sendMessage.setIconType(actFlowPublishConfigEntity.getIconType());
                sendMessage.setSummary(ELUtils.getSummary(actFlowPublishConfigEntity.getSummary(),actFlowPublishConfigEntity.getManyConditionJson(),formData));
            }

            actMessageService.sendMessage(sendMessage, MessageType.copy);
            //触发回调
            flowCallbackManagementService.callback(sendMessage,MessageType.copy.getType());

        }
    }
}
